/***************************************************************
|	File:		Entity.cpp
|	Author:		Almando R. Santos Jr.
|	Course:		SGD
|	Purpose:	Entity class stores the shared data members
|				for all child game entities
***************************************************************/

#include "Entity.h"

#include "../SGD Wrappers/SGD_GraphicsManager.h"
#include <math.h>
#include <cassert>

Entity::Entity(void)
: Listener(this)
{
	Listener::RegisterForEvent("SMASH!");
}

/**************************************************************/
// DESTRUCTOR
/*virtual*/ Entity::~Entity(void)
{
	Listener::UnregisterFromEvent("SMASH!");
	assert(m_unRefCount == 0 && "~Entity - entity was destroyed while references remain!");
}


/**************************************************************/
// Update
//	- move the entity's position by its velocity
/*virtual*/ void Entity::Update(float elapsedTime)
{
	if (m_bAerial == true)
	{
		if (SGD::Vector(m_ptDestPos - m_ptPosition).ComputeLength() <= 20 && m_bIsHeld == false)
		{
			m_bAerial = false;
			m_fHeight = 0;
			m_vtVelocity = { 0, 0 };
		}

		m_bIsHeld = false;
		m_bIsActive = true;
		m_fHeight += m_vtAerialVel.y * elapsedTime;
		m_vtAerialVel.y += 40 * elapsedTime;
		m_ptPosition += m_vtAerialVel * elapsedTime;
		m_ptShadowPos += m_vtVelocity * elapsedTime;
	}	
	else if (m_fSmashStun > 0)
		m_ptPosition += m_vtSmashVel * elapsedTime;
	else
		m_ptPosition += m_vtVelocity * elapsedTime; 

	m_fSmashStun -= elapsedTime;


}


/**************************************************************/
// Render
//	- draw the entity's image at its position
/*virtual*/ void Entity::Render(void)
{
	// Verify the image
	//assert( m_hImage != SGD::INVALID_HANDLE && "Entity::Render - image was not set!" );


	// Draw the image
	/*SGD::GraphicsManager::GetInstance()->DrawTexture(
		m_hImage, m_ptPosition,
		m_fRotation, m_szSize/2 );*/
	SGD::GraphicsManager::GetInstance()->DrawRectangle({ m_ptPosition, m_szSize }, m_TempColor);

}


/**************************************************************/
// GetRect
//	- calculate the entity's bounding rectangle
/*virtual*/ SGD::Rectangle Entity::GetRect(void) const
{
	return SGD::Rectangle{ m_ptPosition, m_szSize };
}


/**************************************************************/
// HandleCollision
//	- respond to collision between entities
/*virtual*/ void Entity::HandleCollision(const Entity* pOther)
{
	/* DO NOTHING */
	(void)pOther;		// unused parameter
}

/*virtual*/ void Entity::HandleEvent(const SGD::Event*  pEvent)
{
	if (pEvent->GetEventID() == "SMASH!" && this != reinterpret_cast<Entity*>(pEvent->GetSender()) && GetType() != ENT_WALL && GetType() != ENT_BALL && GetType() != ENT_PUP && GetType() != ENT_PUNCH)
	{
		m_vtSmashVel = SGD::Vector(m_ptPosition - reinterpret_cast<Entity*>(pEvent->GetSender())->GetPosition());

		if (*(reinterpret_cast<int*>(pEvent->GetData())) == 1)
		{
			if (m_vtSmashVel.ComputeLength() <= 70)
			{
				m_vtSmashVel.Normalize();

				if (GetType() == ENT_GORBI)
					m_vtSmashVel *= 20;
				else if (GetType() == ENT_CANNYBLE)
					m_vtSmashVel *= 50;
				else
					m_vtSmashVel *= 40;

				m_fSmashStun = 0.25f;
			}
		}
		else if (*(reinterpret_cast<int*>(pEvent->GetData())) == 2)
		{
			if (m_vtSmashVel.ComputeLength() <= 140)
			{
				m_vtSmashVel.Normalize();

				if (GetType() == ENT_GORBI)
					m_vtSmashVel *= 40;
				else if (GetType() == ENT_CANNYBLE)
					m_vtSmashVel *= 100;
				else
					m_vtSmashVel *= 80;

				m_fSmashStun = 0.5f;
			}
		}
		else if (*(reinterpret_cast<int*>(pEvent->GetData())) == 3)
		{
			if (m_vtSmashVel.ComputeLength() <= 210)
			{
				m_vtSmashVel.Normalize();

				if (GetType() == ENT_GORBI)
					m_vtSmashVel *= 60;
				else if (GetType() == ENT_CANNYBLE)
					m_vtSmashVel *= 150;
				else
					m_vtSmashVel *= 120;

				m_fSmashStun = 1;
			}
		}
	}
}


/**************************************************************/
// AddRef
//	- increase the reference count
/*virtual*/ void Entity::AddRef(void)
{
	assert(m_unRefCount != 0xFFFFFFFF && "Entity::AddRef - maximum reference count has been exceeded");

	++m_unRefCount;
}


/**************************************************************/
// Release
//	- decrease the reference count
//	- self-destruct when the count is 0
/*virtual*/ void Entity::Release(void)
{
	--m_unRefCount;

	if (m_unRefCount == 0)
		delete this;
}

void Entity::RotatePlayers(Entity* player, float angle, SGD::Point center)
{
	float s = sin(angle);
	float c = cos(angle);

	// translate point back to origin:
	SGD::Point temp{ player->GetPosition().x - center.x, player->GetPosition().y - center.y };

	// rotate point
	float newX = temp.x * c - temp.y * s;
	float newY = temp.x * s + temp.y * c;

	// translate point back:
	temp.x = newX + center.x;
	temp.y = newY + center.y;

	player->SetPosition(temp);
}